package com.ruoyi.system.controller;

import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.SeckillInfo;
import com.ruoyi.system.domain.SeckillRecord;
import com.ruoyi.system.domain.UserInfo;
import com.ruoyi.system.service.ISeckillInfoService;
import com.ruoyi.system.service.ISeckillRecordService;
import com.ruoyi.system.service.IUserInfoService;
import com.ruoyi.system.tool.tool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 秒杀信息Controller
 * 
 * @author sjt
 * @date 2021-11-30
 */
@RestController
@RequestMapping("/SeckillModularController")
public class SeckillModularController extends BaseController
{
    @Autowired
    private ISeckillInfoService seckillInfoService;

    @Autowired
    private IUserInfoService userInfoService;

    @Autowired
    private ISeckillRecordService seckillRecordService;

    @Autowired
    private RedisService redisService;

    /**
     * 主播发起秒杀
     */
    @PostMapping("/onshelve")
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public AjaxResult onshelve(@RequestBody SeckillInfo seckillInfo)
    {
        if(seckillInfo.getUserId()==null){
            return AjaxResult.error("未传入用户编号");
        }else {
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(seckillInfo.getUserId());
            List<UserInfo> userlist = userInfoService.selectUserInfoList(userInfo);
            if(userlist.size()!=1){
                return AjaxResult.error("用户不存在/非法");
            }
        }
        if(seckillInfo.getStartTime()==null||seckillInfo.getEndTime()==null||seckillInfo.getSeckillNum()==null){
            return AjaxResult.error("传入参数存在空值");
        }
        if(seckillInfo.getStartTime().after(seckillInfo.getEndTime())){
            return AjaxResult.error("结束时间不能小于开始时间");
        }
        if(seckillInfo.getSeckillNum()<1l){
            return AjaxResult.error("商品数量不能小于1");
        }
        seckillInfo.setSeckillType("1");
        seckillInfoService.insertSeckillInfo(seckillInfo);
        return AjaxResult.success(seckillInfo);
    }

    /**
     * 用户获取秒杀信息
     */
    @PostMapping("/getshelve")
    public AjaxResult getshelve(@RequestBody SeckillInfo seckillInfo)
    {
        List<SeckillInfo> seckillInfolist = seckillInfoService.selectSeckillInfoList(seckillInfo);
        int size = seckillInfolist.size();
        if(size==0){
            return AjaxResult.error("主播暂未发布秒杀");
        }else{
            Date nowDate = tool.getDate();
            Date startDate = seckillInfolist.get(size-1).getStartTime();
            Date endDate = seckillInfolist.get(size-1).getEndTime();
            if(nowDate.before(startDate)){
                return AjaxResult.error("秒杀未开始");
            }else if(nowDate.after(endDate)){
                return AjaxResult.error("秒杀已结束");
            }else{
                return AjaxResult.success(seckillInfolist.get(size-1));
            }
        }
    }

    /**
     * 用户参与秒杀
     */
    @PostMapping("/joinshelve")
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public AjaxResult joinshelve(@RequestBody SeckillRecord seckillRecord)
    {
        //判空
        if(seckillRecord.getSeckillId()==null){
            return AjaxResult.error("未传入秒杀编号");
        }else if(seckillRecord.getUserId()==null){
            return AjaxResult.error("未传入用户编号");
        }
        Long userId = seckillRecord.getUserId();
        //获取秒杀信息
        SeckillInfo seckillInfo = seckillInfoService.selectSeckillInfoBySeckillId(seckillRecord.getSeckillId());
        if(seckillInfo.getSeckillType().equals("0")){
            return AjaxResult.error("秒杀已结束");
        }
        Date nowDate = tool.getDate();
        Date startDate = seckillInfo.getStartTime();
        Date endDate = seckillInfo.getEndTime();
        Long num = seckillInfo.getSeckillNum();
        if(seckillRecord.getUserId().equals(seckillInfo.getUserId())){
            return AjaxResult.error("不能抢购自己的商品");
        }
        //判断秒杀开始时间
        if(nowDate.before(startDate)){
            return AjaxResult.error("秒杀未开始");
        }else if(nowDate.after(endDate)){
            seckillInfo.setSeckillType("0");
            seckillInfoService.updateSeckillInfo(seckillInfo);
            return AjaxResult.error("秒杀已结束");
        }
        //Redis数据读取/写入进程锁
        synchronized (this) {
            //读取Redis缓存秒杀数量，没有则新增
            String key = "ms" + String.format("%06d", seckillRecord.getSeckillId());
            List<Long> userList = new ArrayList();
            if (!redisService.hasKey(key)) {
                redisService.setCacheObject(key, userList);
            }
            userList = redisService.getCacheObject(key);
            //判断用户是否重复抢购
            for (Long user : userList) {
                if (user == userId) {
                    return AjaxResult.error("已抢购商品，请勿重复抢购");
                }
            }
            //判断商品剩余量
            userList.add(userId);
            if (userList.size() > num) {
                seckillInfo.setSeckillType("0");
                seckillInfoService.updateSeckillInfo(seckillInfo);
                return AjaxResult.error("商品已被抢完");
            }
            redisService.setCacheObject(key, userList);
        }
        //写入秒杀数据
        seckillRecord.setSeckillTime(nowDate);
        seckillRecord.setPayType("0");
        seckillRecord.setSeckillType("1");
        seckillRecordService.insertSeckillRecord(seckillRecord);
        return AjaxResult.success("成功抢到了商品，请立即支付");
    }
}
